import { DefaultMakeMessage } from "./DefaultMakeMessage";
import { Logger } from "./Logger";
import { MakeMessage } from "./MakeMessage";

class Console {
}

const consoleContext = new Console();

class LoggerManagerClass {
  private _loggerMap: Map<string, Logger> = new Map();

  private makeMessage: MakeMessage = new DefaultMakeMessage()

  private _console_intercept: boolean = false;
  private consoleBundle = {
    type: 0,
    log: console.log,
    warn: console.warn,
    info: console.info,
    trace: console.trace,
    error: console.error,
    debug: console.debug
  }

  setDefaultType(type: number) {
    Logger.DEFAULT_TYPE = type;
  }

  /**
   * 获取Class或Struct的Logger
   * @param context 类或类名
   * @returns Logger
   * @since 1.0.0
   */
  getLogger<T extends Object>(context: T | string, type: number = Logger.DEFAULT_TYPE): Logger {
    let key = 'Anonymous';
    if (typeof context == 'string') {
      key = context;
    } else if (context && context.constructor) {
      key = context.constructor.name;
    }
    key = key + "---type---" + type;
    if (this._loggerMap.has(key)) {
      return this._loggerMap.get(key)!;
    }
    const l = this.createLogger(key);
    this._loggerMap.set(key, l);
    return l;
  }

  /**
   * 拦截所有console.log日志
   * @since 1.3.1
   */
  interceptConsole(type: number): void {
    if (this._console_intercept) {
      return;
    }
    this.consoleBundle.type = type;
    this._console_intercept = true;
    let types = ['log', 'error', 'debug', 'warn', 'trace', 'info'];
    types.forEach(type => {
      this.consoleBundle[type] = console[type];
      console[type] = (...args: any[]) => {
        let format = '';
        for (let i = 0; i < args.length; i++) {
          let type = typeof args[i] == 'object' ? '%j ' : '%s '
          format += type;
        }
        let Console = this.console();
        if (type == 'log') {
          type = 'info';
        }
        if (type == 'trace') {
          type = 'warn';
        }
        Console[type](format, ...args)
      }
    });
  }

  private console(): Logger {
    if (this._loggerMap.has(consoleContext.constructor.name)) {
      return this._loggerMap.get(consoleContext.constructor.name);
    }
    const l = this.createLogger(consoleContext.constructor.name);
    this._loggerMap.set(consoleContext.constructor.name, l);
    return this._loggerMap.get(consoleContext.constructor.name);
  }

  private createLogger(tag: string) {
    return new Logger(tag, this.makeMessage);
  }
}

export const LoggerManager = new LoggerManagerClass();